package com.demo2do.fms.admin.web.controller.business;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.utils.WebUtils;
import com.demo2do.fms.admin.dto.OtherFeeInfo;
import com.demo2do.fms.admin.entity.report.ExportType;
import com.demo2do.fms.admin.entity.report.business.ShipmentReportSearch;
import com.demo2do.fms.admin.entity.search.business.ShipmentSearch;
import com.demo2do.fms.admin.entity.security.Login;
import com.demo2do.fms.admin.service.business.DispatchOrderService;
import com.demo2do.fms.admin.service.business.ShipmentService;
import com.demo2do.fms.admin.service.data.DefaultOilTypeService;
import com.demo2do.fms.admin.utils.FormatUtils;
import com.demo2do.fms.admin.visitor.impl.PersistentVisitor;
import com.demo2do.fms.admin.web.resolver.Secure;
import com.demo2do.fms.admin.web.view.ExcelTemplateView;
import com.demo2do.fms.entity.business.Shipment;
import com.demo2do.fms.entity.business.shipment.DispatchOrder;
import com.demo2do.fms.entity.business.shipment.ShipmentLine;
import com.demo2do.fms.entity.business.shipment.ShipmentOrder;
import com.demo2do.fms.entity.business.shipment.TransportCost;
import com.demo2do.fms.entity.data.business.OtherFeeType;

/**
 * 安吉指令调度查询、生成派车单
 * 
 * @author Wy
 * 
 */
@Controller
@RequestMapping("/shipment-lines")
@MenuSetting("menu-business")
public class ShipmentLineController {

	private static final Logger logger = LoggerFactory.getLogger(ShipmentLineController.class);

	@Autowired
	private ShipmentService shipmentService;

	@Autowired
	private DispatchOrderService dispatchOrderService;

	@Autowired
	private DefaultOilTypeService defaultOilTypeService;

	@Autowired
	private PersistentVisitor persistentVisitor;

	/**
	 * 
	 * 查询安吉调度指令 / 生成派车单 - 查询页 / 生成 派车单 - 查询页
	 * 
	 * target - search - 查询安吉调度指令 target - generate - 生成派车单 target - generate-update
	 * 生成修改派车单
	 * 
	 * @param login
	 * @param target
	 * @return
	 */
	@MenuSetting("submenu-shipment-{target}")
	@RequestMapping(value = "/search", method = RequestMethod.GET, params = "target")
	public ModelAndView search(@Secure Login login, @RequestParam("target") String target) {

		ModelAndView modelAndView = new ModelAndView("business/shipment/shipment-search");

		modelAndView.addObject("region", login.isRegionUser());
		modelAndView.addObject("orgIds", login.getCurrOrgIds());

		modelAndView.addObject("target", target);

		return modelAndView;

	}

	/**
	 * 查询安吉调度指令 / 生成派车单-查询
	 * 
	 * target - search - 查询安吉调度指令 target - generate - 生成派车单 target - generate-update
	 * - 生成修改派车单
	 * 
	 * @param shipmentSearch
	 * @param page
	 * @param request
	 * @param session
	 * @return
	 */
	@MenuSetting("submenu-shipment-{target}")
	@RequestMapping(value = "", method = RequestMethod.GET, params = { "filter", "target" })
	public ModelAndView onSearch(ShipmentSearch shipmentSearch, HttpServletRequest request, HttpSession session, Page page) {

		String target = shipmentSearch.getTarget();

		session.setAttribute("generateQueryString", request.getQueryString());

		String resultPage = "business/shipment/shipment-";
		if (StringUtils.equals("generate", target)) {
			resultPage += "generate-list";
		}
		if (StringUtils.equals("search", target)) {
			resultPage += "list";
		}
		if (StringUtils.equals("generate-update", target)) {
			resultPage += "generate-update-list";
		}

		ModelAndView modelAndView = new ModelAndView(resultPage);
		modelAndView.addObject("target", target);

		int totals = shipmentService.countShipment(shipmentSearch);
		if (totals > 0) {

			List<ShipmentLine> shipments = shipmentService.listShipment(shipmentSearch, page.with(totals));

			modelAndView.addObject("shipments", shipments);
			modelAndView.addObject("page", page);
			modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page", "filter"));

		}

		return modelAndView;

	}

	/**
	 * 生成派车单时的校验
	 * 
	 * @param loadNumber
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/validate", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	public @ResponseBody HttpResult validateDispatchOrderGenerate(@PathVariable("loadNumber") String loadNumber,
			@RequestParam("target") String target) {

		HttpResult httpResult = new HttpResult();

		try {

			shipmentService.validateDispatchOrderGenerate(loadNumber);

			httpResult.success().message("校验通过").data("url",
					"/shipment-lines/" + loadNumber + "/prepare?target=" + target);

		} catch (BusinessException e) {
			logger.error("#validateDispatchOrderGenerate() - generate dispatch order validate fail, exception is [{}]",
					e);
			httpResult.fail("").message(e.getMessage());
		}

		return httpResult;
	}

	/**
	 * 新建派车单 - 准备
	 * 
	 * @param loadNumber
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/prepare", method = RequestMethod.GET, params = { "target" })
	@MenuSetting("submenu-shipment-{target}")
	public ModelAndView prepare(@PathVariable("loadNumber") String loadNumber, @RequestParam("target") String target) {

		
		ModelAndView modelAndView = new ModelAndView();
		
		String resultPage = "business/shipment/shipment-" + (StringUtils.equals("generate", target) ? "generate-prepare" : "generate-update");
		modelAndView.setViewName(resultPage);

		// 1. load shipment_line
		ShipmentLine shipmentLine = shipmentService.loadShipmentLine(loadNumber);

		// 2. load dispatch_order by load_group_number
		DispatchOrder dispatchOrder = dispatchOrderService.loadDispatchOrder(shipmentLine.getShipmentGroup());

		Long defaultOilTypeId = null;
		List<ShipmentOrder> shipmentOrders = null;
		List<OtherFeeType> otherFeeTypes = null;

		if (dispatchOrder != null) {

			// 3.1.1 get oil_type_id
			TransportCost transportCost = dispatchOrderService.getTransportCost(dispatchOrder.getId());
			defaultOilTypeId = (transportCost == null ? 0 : transportCost.getOilTypeId());

			// 3.1.2 get shipment_orders by dispatch_order or load_number
			shipmentOrders = shipmentService.listShipmentOrder(dispatchOrder.getId(), loadNumber);
			
			// 4. get other_fee by dispatch_order
            // key - fee_type_id
            // value - other_fee_info
            Map<Long, OtherFeeInfo> otherFeeMap = dispatchOrderService.getOtherFeeMappings(dispatchOrder.getId());
            
            modelAndView.addObject("transportCost", transportCost);
            modelAndView.addObject("otherFeeMap", otherFeeMap);  

		} else {

			// 3.2.1 pre-generate dispatch_order
			dispatchOrder = shipmentService.preGenerateDispatchOrder(shipmentLine);

			// 3.2.2 get oil_type_id
			defaultOilTypeId = defaultOilTypeService.getDefaultOilTypeId(shipmentLine.getTransCorpId());

			// 3.2.3 get shipment_orders by load_number
			shipmentOrders = shipmentService.listShipmentOrder(loadNumber);
			
			// 3.2.4 get other fee types
            otherFeeTypes = dispatchOrderService.listOtherFeeTypes();

		}

		modelAndView.addObject("target", target);
		
		modelAndView.addObject("shipmentLine", shipmentLine);
		modelAndView.addObject("dispatchOrder", dispatchOrder);
		modelAndView.addObject("shipmentOrders", shipmentOrders);
		modelAndView.addObject("defaultOilTypeId", defaultOilTypeId);
		modelAndView.addObject("loadNumber", loadNumber);
		modelAndView.addObject("otherFeeTypes", otherFeeTypes);

		return modelAndView;

	}

	/**
	 * 新建派车单 - 准备
	 * 
	 * @param loadNumber
	 * @param dispatchOrderId
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/prepare-shipment-order", method = RequestMethod.GET)
	@MenuSetting("submenu-shipment-generate")
	public ModelAndView prepareShipmentOrder(@PathVariable("loadNumber") String loadNumber, Long dispatchOrderId) {

		ModelAndView modelAndView = new ModelAndView("business/shipment/shipment-generate-prepare-shipment-order");

		List<ShipmentOrder> shipmentOrders = null;

		if (dispatchOrderId != -1) {

			// get shipment_orders by dispatch_order or load_number
			shipmentOrders = shipmentService.listShipmentOrder(dispatchOrderId, loadNumber);

		} else {

			// get shipment_orders by load_number
			shipmentOrders = shipmentService.listShipmentOrder(loadNumber);

		}

		modelAndView.addObject("shipmentOrders", shipmentOrders);

		return modelAndView;

	}

	/**
	 * 新建派车单 - 执行
	 * 
	 * @param login
	 * @param dispatchOrder
	 * @param oilTypeId
	 * @param loadNumber
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/generate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	public @ResponseBody HttpResult onGenerate(@Secure Login login, @PathVariable("loadNumber") String loadNumber,
			DispatchOrder dispatchOrder, @RequestParam(name = "oilTypeId") Long oilTypeId) {

		HttpResult httpResult = new HttpResult();

		try {

			// 1. generate
			Long dispatchOrderId = shipmentService.generateDispatchOrder(dispatchOrder, loadNumber, oilTypeId, login);

			// 2. get dispatch_order by id
			DispatchOrder existDispatchOrder = dispatchOrderService.loadDispatchOrder(dispatchOrderId);

			httpResult.success().message("生成派车单成功! 生成的派车单号为：" + existDispatchOrder.getCode());   // FIXME 生成派车单post请求后的跳转，目前为详情页，是否修改？

		} catch (BusinessException e) {
			logger.error("#onGenerate() - generate dispatch order fail, exception is [{}]", e);
			httpResult.fail("500").message(e.getMessage());
		}

		return httpResult;

	}
	/**
	 * 修改派车单中新建派车单 - 执行
	 * 
	 * 
	 * 
	 * @param login
	 * @param dispatchOrder
	 * @param oilTypeId
	 * @param loadNumber
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/generate-update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	public @ResponseBody HttpResult onGenerateUpdate(@Secure Login login,
													 @PathVariable("loadNumber") String loadNumber,
													 DispatchOrder dispatchOrder, 
													 @RequestParam(name = "oilTypeId") Long oilTypeId,
													 @RequestParam("adjustmentDistance") BigDecimal adjustmentDistance, 
													 @RequestParam("roadFee") BigDecimal roadFee,
		                                             @RequestParam(value = "otherFeeTypeIds") List<Long> otherFeeTypeIds,
		                                             @RequestParam(value = "otherFees", required = false) List<BigDecimal> otherFees,
		                                             @RequestParam("otherFeeAuditor") String otherFeeAuditor
													
													 ) {
		
		// FIXME 指令组都无派车单时，其他费用和路桥费等信息没保存成功
		
		HttpResult httpResult = new HttpResult();

		try {

			// 1. generate
			Long dispatchOrderId =shipmentService.generateUpdateDispatchOrder(dispatchOrder, loadNumber, oilTypeId, adjustmentDistance, roadFee, otherFeeTypeIds, otherFees, login, otherFeeAuditor);
			
			// 2. get dispatch_order by id
			DispatchOrder existDispatchOrder = dispatchOrderService.loadDispatchOrder(dispatchOrderId);
			
			httpResult.success().message("生成派车单成功! 生成的派车单号为：" + existDispatchOrder.getCode())
								.data("url", "/shipment-lines/"+ loadNumber+"/generate-view?dispatchOrderId=" + dispatchOrderId);
			

		} catch (BusinessException e) {
			logger.error("#onGenerate() - generate dispatch order fail, exception is [{}]", e);
			httpResult.fail("500").message(e.getMessage());
		}

		return httpResult;

	}
	
	/**
	 *
	 * @param dispatchOrderId
	 * @return
	 */
	@RequestMapping(value = "/{loadNumber}/generate-view", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@MenuSetting("submenu-shipment-generate-update")
	public ModelAndView generateResultView(@PathVariable("loadNumber") String loadNumber, @RequestParam("dispatchOrderId") Long dispatchOrderId) {
		
		ModelAndView modelAndView = new ModelAndView("business/shipment/shipment-generate-update-view");
    	
    	DispatchOrder dispatchOrder = dispatchOrderService.loadDispatchOrder(dispatchOrderId);
    	
    	// 3.1.1 get oil_type_id
        TransportCost transportCost = dispatchOrderService.getTransportCost(dispatchOrder.getId());
        
        // 3.1.2 get shipment_orders by dispatch_order or load_number
        List<ShipmentOrder> shipmentOrders = shipmentService.listShipmentOrder(dispatchOrder.getId(), loadNumber);
        
        // 4. get other_fee by dispatch_order
        // key - fee_type_id
        // value - other_fee_info
        Map<Long, OtherFeeInfo> otherFeeMap = dispatchOrderService.getOtherFeeMappings(dispatchOrder.getId());
        
        modelAndView.addObject("transportCost", transportCost);
        modelAndView.addObject("dispatchOrder", dispatchOrder);
        modelAndView.addObject("shipmentOrders", shipmentOrders);
        modelAndView.addObject("loadNumber", loadNumber);
        modelAndView.addObject("otherFeeMap", otherFeeMap);
    	
    	return modelAndView;

	}
	
	
	/**
	 * 输出当前页记录
	 * 
	 * @param search
	 * @param page
	 * @return
	 */
	@RequestMapping(value = "/export", method = RequestMethod.GET)
	public ModelAndView export(ShipmentSearch search, Page page) {

		String template = "business/shipment" + (StringUtils.equals("generate", search.getTarget()) ? "-generate" : "")
				+ "-export.xlsx";
		ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView(template));

		// 1. list shipment line
		int totals = shipmentService.countShipment(search);
		if (totals > 0) {

			List<ShipmentLine> shipments = shipmentService.listShipment(search, page.with(totals));
			modelAndView.addObject("shipments", shipments);

		}

		// 2. attribute
		modelAndView.addObject("persist", persistentVisitor);
		modelAndView.addObject("type", ExportType.CURRENT);

		// 3. format util
		FormatUtils fmt = new FormatUtils();
		modelAndView.addObject("fmt", fmt);

		return modelAndView;

	}

	/**
	 * 输出所有记录
	 * 
	 * @param search
	 * @return
	 */
	@RequestMapping(value = "/export-all", method = RequestMethod.GET)
	public ModelAndView exportAll(ShipmentReportSearch search) {

		String template = "business/shipment" + (StringUtils.equals("generate", search.getTarget()) ? "-generate" : "")
				+ "-export.xlsx";
		ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView(template));

		// 1. list result
		List<Map<String, Object>> results = shipmentService.exportAll(search);
		modelAndView.addObject("results", results);

		// 2. attribute
		modelAndView.addObject("type", ExportType.ALL);

		// 3. format util
		FormatUtils fmt = new FormatUtils();
		modelAndView.addObject("fmt", fmt);

		logger.warn("#exportAll() - export size=[{}]...", results.size());

		return modelAndView;

	}

	/**
	 * 
	 * @param shipmentId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/{shipmentId}/electronic", method = RequestMethod.GET)
	@MenuSetting("submenu-trans-order")
	public ModelAndView electronic(@PathVariable("shipmentId") Long shipmentId) {

		ModelAndView modelAndView = new ModelAndView("business/shipment/shipment-view-electronic");

		// 1. load shipment
		Shipment shipment = shipmentService.loadShipment(shipmentId);

		// 2. get result
		HttpResult httpResult = shipmentService.getElectronicImage(shipment);
		if (httpResult != null && httpResult.isValid()) {
			List<String> urls = (List<String>) httpResult.getData().get("urls");
			modelAndView.addObject("urls", urls);
		}

		return modelAndView;

	}

}